#include <iostream>
#include <array>
#include <tuple>
#include <string>
#include <sstream>

#include <iostream>
using namespace std;

/*
参考TraitsLearn3

解决传入参数问题

*/
namespace TraitsLearn4 {

    /*假设有一个未知类*/
    template <class T>
    struct unknown_class  {
        typedef T type;
    };

    /*先定义一些tag*/
    struct A :unknown_class<A> {
        float a;
    };
    struct B : unknown_class<B> {
        float b;
    }; 
    template <class T>
    struct C : unknown_class<T> {
        T value;
    };
   

    /*特性萃取器  获取到返回类型*/
    template <class T>
    struct unknown_class_traits {
        typedef typename T::type type;
    };

    /*特性萃取器 —— 针对原生指针*/
    template <class T>
    struct unknown_class_traits<T*> {
        typedef T type;
    };

    /*特性萃取器 —— 针对指向常数*/
    template <class T>
    struct unknown_class_traits<const T*> {
        typedef const T type;
    };


    /*决定使用哪一个类型*/
    /*
    template <class T>
    inline typename unknown_class_traits< T>::type
        type(T) {
        typedef typename unknown_class_traits< T>::type RT;
        return RT();
    }
    */
    template <class T>
    inline typename unknown_class_traits<T>::type
        __func(T u, A) {
        A a1=u;
        cout << "u.a="<<u.a << endl;
        a1.a += 10;
        cout << "use A flag" << endl;
        return a1;
    }

    template <class T1>
    inline typename unknown_class_traits<T1>::type
        __func(T1 u, B) {
        cout << "u.b=" << u.b << endl;
        cout << "use B flag" << endl;
        return B();
    }

 
    template <typename T1, class T>
    T __func(T1 u, T) {// func传来t，无意义
        T* t1 = u;
        char* ptr;
        uintptr_t number = (uintptr_t)ptr;
        cout << "use origin ptr" << endl;
        cout << "u=" << u << endl;
        cout << "*u=" << *u << endl;
        return *u*2;
    }

    template <class T>
    inline typename unknown_class_traits<T>::type
        func(T u) {
        typedef typename unknown_class_traits<T>::type type;
        return __func(u, type());//  编译器 会匹配 类型   type()无用的参数，主要是取其类型，用来匹配具体的实现函数 __func(T1 u, B b)
    }

    int main() {

        A a;
        B b;

        C<int> x1;//不支持
        x1.value = 100;
        //       int v7 = func(x1); //会导致编译错误

        int value = 1;
        int* p = &value;

        float f =2;
        float* pFloat = &f;

        a.a = 20;
        A v1 = func(a);
        cout << " v1.a=" << v1.a << endl;
       
        b.b = 30;
        B v2 = func(b);
        cout << " v2=" << v2.b << endl;

        int v3 = func(p);
        cout << " v3=" << v3 << endl;
       float v4 = func(pFloat);
       cout << " v4=" << v4 << endl;
       
       float v5 = func(&f);
       cout << " v5=" << v5 << endl;


       

        unknown_class<int> x;//无意义，无法赋值，无法读值
        unknown_class<float> y;//无意义，无法赋值，无法读值
         //       int v5 = func(x);  //会引起模板编译出错
 //       float v6 = func(y);

        return 0;
    }
   
}